#ifndef _OBLFairTable_H_
#define _OBLFairTable_H_

#include "sthread.h"

static const int NO_PHILOSOPHER = -1;
static const int TABLE          =  1;
static const int F_SERVANT      =  2;
static const int C_SERVANT      =  3;

typedef int Philosopher;

typedef struct NodeS{
  struct NodeS* next;
  struct NodeS* prev;
  Philosopher phil;
} Node;

typedef struct OBLFairTableS{
  smutex_t     mutex;           // master lock, used to ensure code's mutual exclusion
  scond_t      cond;            // condition var conditioning if philosopher is eligible to eat
  scond_t      cond2;           // condition var conditioning if filling servant is ready to fill

  int*         chopsticks;      // chopsticks array; value at i is 1 if ith chopstick is held, 0 otherwise
  int*         plates;          // plates array; value at i is 0 if plate held by ith philosopher, 1 if held cleaning servant (no other possiblities)
  int*         hasEaten;        // boolean array of philosophers that have started eating since plates were last cleaned

  int          bowl;
  int          bowl_status;     // TABLE, F_SERVANT, or C_SERVANT
  int          cleaning_mode;   // prevent filling servant from getting bowl if cleaner already gathered plates, chopsticks, (or bowl), but not if cleaner already returned bowl

  int          N;               // number of philosophers

  Node*        front;           // pointer to front of hunger queue
  Node**       nodes;           // array of Node pointers

} OBLFairTable;

void OBLF_init(OBLFairTable *t, int nPlates);
void OBLF_startEating(OBLFairTable *t, int philosopher);
void OBLF_doneEating(OBLFairTable *t, int philosopher);
void OBLF_takeEmptyBowl(OBLFairTable *t);
void OBLF_returnRefilledBowl(OBLFairTable *t, int servingCount);
void OBLF_waitUntilAllPlatesDirty(OBLFairTable *t);
void OBLF_gatherSticks(OBLFairTable *t);
void OBLF_gatherBowl(OBLFairTable *t);
void OBLF_gatherPlates(OBLFairTable *t);
void OBLF_returnSticks(OBLFairTable *t);
void OBLF_returnBowl(OBLFairTable *t);
void OBLF_returnPlates(OBLFairTable *t);

// some of my functions
int timeToClean(OBLFairTable *t);
int allPlatesDirty(OBLFairTable *t);

#endif 
